package project;

import java.util.LinkedList;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

import project.SimulationStatistics;
/*
 * 
 * 
 * For Reference:
 * Time in Hours:		8	9	10	11	12	1	2	3	4	5
 * Time in Minutes:		0	60	120	180	240	300	360	420	480	540
 */
public class Manager extends Thread
{

	private final String name;
	private boolean busy;
	
	private CyclicBarrier manBarrier;
	SimulationStatistics stats;
	private boolean atWork = false;
	private boolean completedAfternoonMeeting = false;
	
	private LinkedList<Employee> queue = new LinkedList<Employee>();
	private int waitedTime;
	
	
	public Manager (CyclicBarrier cyclicBarrier, String name, SimulationStatistics t)
	{
		this.name = name;
		manBarrier = cyclicBarrier;
		stats = t;
		busy = false;
	}
	
	public void makeAvailable ()
	{
		notifyAll();
		busy = false;
	}
	
	public void makeBusy()
	{
		busy = true;
	}
	
	public boolean isBusy ()
	{
		return busy;
	}
	
	public void run()
	{
		//arrive at work and wait on manBarrier
		System.err.println(stats.getFormattedTime()+": Manager arrives at work");
		atWork = true;
		
		try
		{
			manBarrier.await(); //manBarrier will break once all the Leads wait on it
		} catch (InterruptedException e)
		{
			System.err.println(stats.getFormattedTime()+": Manager was interupted while waiting on manBarrier");
			e.printStackTrace();
		} catch (BrokenBarrierException e)
		{
			System.err.println(stats.getFormattedTime()+": manBarrier was broken");
			e.printStackTrace();
		}
		
		System.err.println(stats.getFormattedTime()+": Manager goes to daily morning standup meeting");
		stayBusy(15);//The manager stays busy in the first meeting for 15 minutes
		
		while(stats.getTime() < 540) //540 is 5pm
		{
			checkBusyTime(stats.getTime());//Check to see if it is time for morning or afternoon manager meeting, or lunch
		
			if((stats.getTime() < 480)) //|| (stats.getTime() >= 510 && stats.getTime() < 530))//Make sure to not answer questions between 4:00-4:15
			{
				checkQuestionQueue();//Manager checks if there are any questions to answer
			}
			
			if(stats.getTime() >= 495 && !completedAfternoonMeeting)//4:15, time for last meeting
			{
				completedAfternoonMeeting = true;
				releaseQuestionQueue();
				System.out.println(stats.getFormattedTime() + " Manager arrives at the afternoon meeting.");
				stayBusy(15);
				System.out.println(stats.getFormattedTime() + " Manager leaves afternoon meeting.");
			}
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		System.err.println(stats.getFormattedTime()+": Manager leaves for the day");
		stats.put(waitedTime, 540, 60, 150);
	}
	
	public void askQuestion(Employee l, Employee d)
	{
		queue.add(l);
		queue.add(d);
	}
	
	public void askQuestion(Employee l)
	{
		queue.add(l);
	}
	
	public void releaseQuestionQueue()
	{
		if(!queue.isEmpty())
		{
			for(Employee e : queue)
			{
				if(e != null)
				{
					synchronized(e)
					{
						e.notify();
					}
				}
			}
		}
		queue.clear();
	}
	
	private void checkQuestionQueue()
	{
		//If there is no one in the queue, don't do anything because we don't have to answer questions
		if(queue.isEmpty())
		{
		}
		else
		{
			System.err.println(stats.getFormattedTime()+": Manager begins answering a question");
			
			//Keep track of the Leader with the question to release later and remove any developers waiting with him
			Employee lWithQuestion = queue.poll();
			Employee dWithQuestion = null;
			if(queue.peek() != null && !queue.peek().isLead())
			{
				dWithQuestion = queue.poll();
			}
			stayBusy(10);
			synchronized(lWithQuestion)
			{
				lWithQuestion.notify();
			}
			if(dWithQuestion != null)
			{
				synchronized(dWithQuestion)
				{
				dWithQuestion.notify();
				}
			}
			System.err.println(stats.getFormattedTime()+": Manager is done answering the question");

		}
	}
	
	private void stayBusy(int length)
	{
		int start = stats.getTime();
		int curr = stats.getTime();
		
		while(stats.getTime() < start + length)
		{
			//If the current time we are tracking is equal to the actual current time in stats, do nothing
			if(curr == stats.getTime())
			{
				continue;
			}
			//Otherwise make the current tracked time equal to real time and calculate question queue waiting time
			else
			{
				curr = stats.getTime();
				if(!queue.isEmpty())
				{
					waitedTime = waitedTime + queue.size();

				}
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

	private void checkBusyTime(int time)
	{
		if(time >= 120 && time < 180) //If time is between 10am and 11am
		{
			System.err.println(stats.getFormattedTime()+": Manager goes to first executive meeting");
			stayBusy(60); //Stay busy at meeting for 1 hour
			System.err.println(stats.getFormattedTime()+": Manager leaves first executive meeting");
		}
		else if(time >= 240 && time < 300) //If time is between 12pm and 1pm
		{
			System.err.println(stats.getFormattedTime()+": Manager goes to lunch");
			stayBusy(60); //Stay busy at lunch for 1 hour
			System.err.println(stats.getFormattedTime()+": Manager leaves lunch");
		}
		else if(time >= 360 && time < 420) //If time is between 2pm and 3pm
		{
			System.err.println(stats.getFormattedTime()+": Manager goes to second executive meeting");
			stayBusy(60); //Stay busy at meeting for 1 hour
			System.err.println(stats.getFormattedTime()+": Manager leaves second executive meeting");
		}
	}
}

